package cn.ydxiaoshuai.pdf;

import cn.hutool.core.date.DateUtil;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.pdf.*;
import com.itextpdf.text.pdf.parser.PdfImageObject;
import com.spire.pdf.FileFormat;
import com.spire.pdf.PdfDocument;
import com.spire.pdf.PdfPageBase;
import com.spire.pdf.exporting.PdfImageInfo;
import com.spire.pdf.graphics.PdfBitmap;
import lombok.extern.slf4j.Slf4j;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.rmi.ServerException;

/**
 * @ClassName PDFCompressUtil
 * @description: POF压缩 耗时较久
 * @author: 小帅丶
 * @create: 2025-01-23 14:49
 * @Version 1.0
 **/
@Slf4j
public class PDFCompressUtil {
    public static long length = 10000000L;
    public static float FACTOR = 0.5f;
    /**
     * @Description POF压缩
     * @param srcPath - 源PDF路径
     * @Author 小帅丶
     * @Date  2025/1/23 15:11:36
     * @return java.io.ByteArrayOutputStream
     **/
    public ByteArrayOutputStream compressPDF(String srcPath) throws Exception{
        return compressPDF(srcPath,20L);
    }
    /**
     * @Description POF压缩
     * @param srcPath - 源PDF路径
     * @param quality - 压缩质量值 0-100 越大质量越高 推荐 20
     * @Author 小帅丶
     * @Date  2025/1/23 15:11:36
     * @return java.io.ByteArrayOutputStream
     **/
    public ByteArrayOutputStream compressPDF(String srcPath,Long quality) throws Exception{
        long startTime = System.currentTimeMillis();
        log.info("[{}][compressPDF]======>参数:srcPath {} quality {}",this.getClass().getSimpleName(),srcPath,quality);
        log.info("[{}][compressPDF]======>开始时间:{}",this.getClass().getSimpleName(),DateUtil.now());
        //Load a sample PDF document
        PdfDocument document = new PdfDocument();
        document.loadFromFile(srcPath);
        int pageNum = document.getPages().getCount();
        if(pageNum > 10){
            log.info("[{}][compressPDF]======>页数超范围:{}",this.getClass().getSimpleName(),pageNum);
           throw new ServerException("PDF页数大于10,无法进行压缩");
        }else{
            if (quality <= 100L && quality >= 0L) {
                document.getFileInfo().setIncrementalUpdate(false);
                for (int i = 0; i < document.getPages().getCount(); i++) {
                    PdfPageBase page = document.getPages().get(i);
                    PdfImageInfo[] images = page.getImagesInfo();
                    if (images != null && images.length > 0)
                        for (int j = 0; j < images.length; j++) {
                            PdfImageInfo image = images[j];
                            PdfBitmap bp = new PdfBitmap(image.getImage());
                            bp.setQuality(quality);
                            page.replaceImage(j, bp);
                        }
                }
                ByteArrayOutputStream[] byteArrayOutputStreams = document.saveToStream(FileFormat.PDF);
                log.info("[{}][compressPDF]======>耗时:{}",this.getClass().getSimpleName(),(System.currentTimeMillis()-startTime));
                log.info("[{}][compressPDF]======>结束时间:{}",this.getClass().getSimpleName(),DateUtil.now());
                return byteArrayOutputStreams[0];
            } else {
                throw new ServerException("质量应在0到100的范围内");
            }
        }
    }

    public static void manipulatePdf(String src, String dest) throws IOException, DocumentException {
        PdfName key = new PdfName("ITXT_SpecialId");
        PdfName value = new PdfName("123456789");
        PdfReader reader = new PdfReader(src);
        int n = reader.getXrefSize();
        PdfObject object;
        PRStream stream;
        for (int i = 0; i < n; i++) {
            object = reader.getPdfObject(i);
            if (object == null || !object.isStream())
                continue;
            stream = (PRStream) object;
            PdfObject pdfsubtype = stream.get(PdfName.SUBTYPE);
            if (pdfsubtype != null && pdfsubtype.toString().equals(PdfName.IMAGE.toString())) {
                PdfImageObject image = new PdfImageObject(stream);
                BufferedImage bi = image.getBufferedImage();
                if (bi == null) continue;
                int width = (int) (bi.getWidth() * FACTOR);
                int height = (int) (bi.getHeight() * FACTOR);
                BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
                AffineTransform at = AffineTransform.getScaleInstance(FACTOR, FACTOR);
                Graphics2D g = img.createGraphics();
                g.drawRenderedImage(bi, at);
                ByteArrayOutputStream imgBytes = new ByteArrayOutputStream();
                ImageIO.write(img, "JPG", imgBytes);
                stream.clear();
                stream.setData(imgBytes.toByteArray(), false, PRStream.BEST_COMPRESSION);
                stream.put(PdfName.TYPE, PdfName.XOBJECT);
                stream.put(PdfName.SUBTYPE, PdfName.IMAGE);
                stream.put(key, value);
                stream.put(PdfName.FILTER, PdfName.DCTDECODE);
                stream.put(PdfName.WIDTH, new PdfNumber(width));
                stream.put(PdfName.HEIGHT, new PdfNumber(height));
                stream.put(PdfName.BITSPERCOMPONENT, new PdfNumber(8));
                stream.put(PdfName.COLORSPACE, PdfName.DEVICERGB);
            }
        }
        PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(dest));
        stamper.close();
        reader.close();
    }

}
